#include "gui/gui_map_interface.h"
#include "gui/gui.h"

#include "city.h"
#include "map.h"
#include "tile.h"
#include "buildable.h"
#include "camera.h"
#include "road.h"

/////////////////////////////////////////////////////
//  GuiMapInterface::GuiMapInterface()
/////////////////////////////////////////////////////
GuiMapInterface::GuiMapInterface(Camera* camera, City* city, sf::RenderWindow* window)
  : tool(nullptr)
{
    this->camera = camera;
    this->city = city;
    this->mainWindow = window;

    int tileSizeX = 16;
    int tileSizeY = 8;

    myCanvas = sfg::Canvas::Create(sfg::Window::Style::BACKGROUND);
    myCanvas->SetZOrder(1);
    myCanvas->SetId("MapWindow");
    myCanvas->SetRequisition(sf::Vector2f(800, 600));
    myCanvas->SetPosition(sf::Vector2f(128, 0));
    myCanvas->GetSignal(sfg::Widget::OnMouseLeftPress).Connect(std::bind(&GuiMapInterface::onLeftClick, this));
    myCanvas->GetSignal(sfg::Widget::OnMouseLeftRelease).Connect(std::bind(&GuiMapInterface::onLeftRelease, this));
}

///////////////////////////////////////////////////////
//  void GuiMapInterface::update(double dt)
///////////////////////////////////////////////////////
void GuiMapInterface::update(double dt)
{
    // Unhighlight the previous tile
    if (lastHighlighted)
    {
        lastHighlighted->setHighlighted(false);
        lastHighlighted = NULL;
    }

    // Highlight the current tile under the mouse
    sf::Vector2i mouseCoord = getMouseTileCoords();
    Tile* tile = city->getMap()->getTile(mouseCoord);

    if (tile)
    {
        tile->setHighlighted(true);
        lastHighlighted = tile;
    }
}

/////////////////////////////////////////////////////////
//  void GuiMapInterface::useTool(sf::Vector2i tileCoord)
/////////////////////////////////////////////////////////
void GuiMapInterface::useTool(sf::Vector2i tileCoord)
{
    if (tool) {
        tool->onUse(tileCoord);
    }
}

///////////////////////////////////////////////////////
//  void GuiMapInterface::setTool()
///////////////////////////////////////////////////////
void GuiMapInterface::setTool(const GuiTool& tool)
{
  this->tool = &tool;
}

///////////////////////////////////////////////////////
//  void GuiMapInterface::onLeftClick()
///////////////////////////////////////////////////////
void GuiMapInterface::onLeftClick()
{
    clickCoord = getMouseTileCoords();
}

/////////////////////////////////////////////////////////
//  void GuiMapInterface::onLeftRelease()
/////////////////////////////////////////////////////////
void GuiMapInterface::onLeftRelease()
{
    sf::Vector2i releaseCoord = getMouseTileCoords();

    // Need to draw a rectangle from the click coord and release coord and determine where to fill
    sf::Vector2i startCoord, endCoord;

    // Find the starting point; filling from upper-left to lower-right
    if (clickCoord.x < releaseCoord.x)
    {
        startCoord.x = clickCoord.x;
        endCoord.x = releaseCoord.x;
    }
    else
    {
        startCoord.x = releaseCoord.x;
        endCoord.x = clickCoord.x;
    }
    // Find the end point; filling from upper-left to lower-right
    if (clickCoord.y < releaseCoord.y)
    {
        startCoord.y = clickCoord.y;
        endCoord.y = releaseCoord.y;
    }
    else
    {
        startCoord.y = releaseCoord.y;
        endCoord.y = clickCoord.y;
    }

    // Fill
    for (int x = startCoord.x; x <= endCoord.x; x++)
    {
        for (int y = startCoord.y; y <= endCoord.y; y++)
        {
            useTool(sf::Vector2i(x, y));
        }
    }
}

////////////////////////////////////////////////////////////////////////
//  sf::Vector2i GuiMapInterface::getMouseTileCoords()
////////////////////////////////////////////////////////////////////////
sf::Vector2i GuiMapInterface::getMouseTileCoords()
{
    // Set mouse tile-coordinates
    // TODO: Mouse coordinates are still weirds
    sf::Vector2i mouse = sf::Mouse::getPosition(*mainWindow);

    int mx = mouse.x + camera->getPos().x;
    int my = mouse.y + camera->getPos().y;

    int x = (mx + 2*my)/32;     // Row reduction of a matrix with the rendering equations
    int y = -x + my/8;          // 32 is 2*tileWidthOffset, 8 is tileHeightOffset

    sf::Vector2i mouseTileCoords(x, y);

    return mouseTileCoords;
}
